package com.dorm.cj;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(StarterService.class)
@EnableConfigurationProperties(StarterServiceProperties.class)
public class StarterAutoConfigure {

    @Autowired
    private StarterServiceProperties properties;

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "example.service", value = "enabled", havingValue = "true")
    StarterService starterService() {
        return new StarterService(properties.getConfig());
    }
}
// https://mp.weixin.qq.com/s/yVc7sQ869ePWnpNwJ3alvw
/*
首先，SpringBoot 在启动时会去依赖的 starter 包中寻找 resources/META-INF/spring.factories 文件，然后根据文件中配置的 Jar 包去扫描项目所依赖的 Jar 包，这类似于 Java 的 SPI 机制。

第二步，根据 spring.factories配置加载AutoConfigure类。
最后，根据 @Conditional注解的条件，进行自动配置并将 Bean 注入 Spring Context 上下文当中。

我们也可以使用
@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自动配置哪些类。
 */
/*
@ConditionalOnClass，当classpath下发现该类的情况下进行自动配置。
@ConditionalOnMissingBean，当Spring Context中不存在该Bean时。
@ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true")，当配置文件中example.service.enabled=true时。
 */

/*
下面列举 SpringBoot 中的所有 @Conditional 注解及作用

@ConditionalOnBean:当容器中有指定的Bean的条件下
@ConditionalOnClass：当类路径下有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器中没有指定Bean的情况下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个，或者在有多个Bean的情况下，用来指定首选的Bean
@ConditionalOnWebApplication:当前项目是Web项目的条件下
 */